package cn.edu.swu.mhans.user.service.impl;

import cn.edu.swu.mhans.common.util.FieldUtils;
import cn.edu.swu.mhans.user.dao.SystemRoleMapper;
import cn.edu.swu.mhans.user.dao.SystemUserMapper;
import cn.edu.swu.mhans.user.dao.SystemUserRolesMapper;
import cn.edu.swu.mhans.user.model.SystemRole;
import cn.edu.swu.mhans.user.model.SystemUser;
import cn.edu.swu.mhans.user.model.SystemUserRoles;
import cn.edu.swu.mhans.user.service.UserService;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.websocket.Session;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ZhanJingbo
 * @version 1.0.0
 * Created on 2018/4/23
 */
@Service
public class UserServiceImpl implements UserService {

    private static Map<String, Session> userWebSocketSessionMap = new ConcurrentHashMap<>();

    @Autowired
    private SystemUserMapper systemUserMapper;
    @Autowired
    private SystemUserRolesMapper systemUserRolesMapper;
    @Autowired
    private SystemRoleMapper systemRoleMapper;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SystemUser user = systemUserMapper.selectByUsername(username);
        if (null == user) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        fillRole(user);
        return user;
    }

    /**
     * 用户注册
     *
     * @param systemUser 待注册用户
     * @return 返回是否注册成功
     */
    @Override
    public boolean register(SystemUser systemUser) {
        SystemUser user = systemUserMapper.selectByUsername(systemUser.getUsername());
        if (null != user) {
            return false;
        }
        Date nowDate = new Date();
        systemUser.setModifyTime(nowDate);
        systemUser.setCreateTime(nowDate);

        SystemRole defaultRole = new SystemRole();
        defaultRole.setId(1L);
        List<SystemRole> roleList = new ArrayList<>();
        roleList.add(defaultRole);
        systemUser.setRoles(roleList);
        return this.add(user);
    }

    @Override
    public void saveUserWebSocketSession(String sessionKey, Session session) {
        userWebSocketSessionMap.put(sessionKey, session);
    }

    @Override
    public Session getUserWebSocketSession(String sessionKey) {
        return userWebSocketSessionMap.get(sessionKey);
    }

    /**
     * 添加
     *
     * @param systemUser 实体
     * @return 是否添加成功
     */
    @Override
    public boolean add(SystemUser systemUser) {
        Long userId = systemUserMapper.insert(systemUser);
        systemUser.setId(userId);
        updateRole(systemUser);
        return true;
    }

    /**
     * 根据id字段对其它非空字段进行修改
     *
     * @param systemUser 实体
     * @return 是否修改成功
     */
    @Override
    public boolean update(SystemUser systemUser) {
        SystemUser entity = findOne(systemUser.getId());
        FieldUtils.copyFileds(systemUser, entity);
        entity.setModifyTime(new Date());
        updateRole(entity);
        return systemUserMapper.updateByPrimaryKey(entity) != 0;
    }

    /**
     * 根据id删除
     *
     * @param id 实体的id
     * @return 是否删除成功
     */
    @Override
    public boolean delete(Long id) {
        return systemUserMapper.deleteByPrimaryKey(id) != 0;
    }

    /**
     * 根据id获取实体
     *
     * @param id 实体
     * @return 查找实体
     */
    @Override
    public SystemUser findOne(Long id) {
        SystemUser user = systemUserMapper.selectByPrimaryKey(id);
        fillRole(user);
        return user;
    }

    /**
     * 获取所有对象
     *
     * @return 对象列表
     */
    @Override
    public List<SystemUser> findAll() {
        List<SystemUser> users = systemUserMapper.selectAll();
        for (SystemUser user : users) {
            fillRole(user);
        }
        return users;
    }

    /**
     * 填充角色信息
     *
     * @param user
     */
    private void fillRole(SystemUser user) {
        List<SystemUserRoles> systemUserRolesList = systemUserRolesMapper.selectByUserId(user.getId());
        List<Long> roleIds = Lists.newArrayList();
        for (SystemUserRoles systemUserRoles : systemUserRolesList) {
            roleIds.add(systemUserRoles.getRolesId());
        }
        List<SystemRole> roleList = systemRoleMapper.findAllByIdIn(roleIds);
        user.setRoles(roleList);
    }

    private void updateRole(SystemUser user) {
        List<SystemUserRoles> userRolesList = systemUserRolesMapper.selectByUserId(user.getId());
        Set<Long> roleIds = Sets.newHashSet();
        for (SystemRole role : user.getRoles()) {
            roleIds.add(role.getId());
            SystemUserRoles systemUserRoles = new SystemUserRoles(user.getId(), role.getId());
            if (userRolesList.contains(systemUserRoles)) {
                continue;
            }
            systemUserRolesMapper.insert(systemUserRoles);
        }
        for (SystemUserRoles systemUserRoles : userRolesList) {
            if (!roleIds.contains(systemUserRoles.getRolesId())) {
                systemUserRolesMapper.deleteByPrimaryKey(systemUserRoles.getId());
            }
        }
    }
}
